package yuyicman.bitmaps 
{
	import caurina.transitions.Tweener;
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import yuyicman.debug.Debugger;
	/**
	 * ...
	 * @author Yuyic.
	 */
	public class FlipPaper extends BitmapPaper 
	{
		
		private const PI		:Number = Math.PI;
		private const HALF_PI	:Number = Math.PI/2;
		
		
		public var flipT		:Number;
		
		private var _offset		:Number;
		private var _target		:DisplayObject;
		
		public function get flipping():Boolean {
			return Tweener.isTweening( this );
		}
		
		public function get target():DisplayObject {
			return _target;
		}
		
		public function FlipPaper( vDiv:int,hDiv:int,width:Number,height:Number ) 
		{
			
			super( vDiv, hDiv, width, height );
			flipT = -PI / 2;
			_offset = 90 / (vDiv * vDiv + hDiv * hDiv);
			
			//addEventListener(Event.ENTER_FRAME, render);
		}
		
		private function _updateFlip():void
        {
			
			var flipA:Number, flipB:Number, flipC:Number;
            var radiusX:Number;
            var radiusY:Number;
            var radiusYr:Number;
			
			var widthRatio:Number 	= _target.width/_width;
			var heightRatio:Number	= _target.height/_height;
			
			graphics.clear();
			
			_callEverySegments( function( bs:BitmapSegment, i:int, j:int ):void {
				
				flipA		= flipT - PI / 180 * (i * _hDiv + j * _vDiv) * _offset;
				flipA 		= Math.min(flipA, HALF_PI);
				flipA 		= Math.max(flipA, -HALF_PI);
				
				flipB 		= (flipA + HALF_PI) / PI;
				flipC 		= 1 - flipB;
				
				radiusX 	= bs._x2 * flipC + bs._x * widthRatio * flipB;
				radiusY 	= bs._y2 * flipC + bs._y * heightRatio * flipB;
				radiusYr	= radiusY * 0.5;
				
				bs.x		= radiusX * Math.sin(flipA);
				bs.y		= radiusY + radiusYr * Math.cos(flipA);
				
				bs.render();
			});
			
			
			
        }
		
		private function _flipComplete():void {
			
			setPaperSize( new Rectangle( 0, 0, _target.width, _target.height ) );
			render();
			swapBd();
			dispatchEvent( new Event( Event.COMPLETE ) );
			
		}
		
		public function flipPaper( time:Number = 3 ):void
        {
			
			var i:int, j:int;
			var pts:Array = [];
			var bs:BitmapSegment;
			
			for ( i = 0; i <= _hDiv; i++ ) {
				pts[i] = [];
				for ( j = 0; j <= _vDiv; j++ ) {
					bs = segmentsList[i][j];
					pts[i][j] = new Point( bs._x2, bs._y2 );
				}
			}
			
			for ( i = _hDiv; i >= 0; i-- ) {
				for ( j = 0; j <= _vDiv; j++ ) {
					bs = segmentsList[i][j];
					bs._x2 = pts[i][j].x;
					bs._y2 = pts[i][j].y;
				}
			}
			
			flipT = -PI / 2;
			
            Tweener.addTween(this, { flipT:PI, time:time, transition:"easeInOutCubic", onUpdate:_updateFlip, onComplete:_flipComplete } );
			
        }
		
		
		public function flipTo( target:DisplayObject, time:Number = 3 ):void {
			
			_target = target;
			setBd1( target );
			
			flipPaper(time);
			
		}
		
		
		public function collapse():void {
			
			var rand:Number;
			var __x:Number;
			var __y:Number;
			
			_callEverySegments( function( bs:BitmapSegment, i:int, j:int ):void {
				
				rand = Math.random() * Math.PI * 468;
                __x = 25 * Math.cos(rand);
                __y = 25 * Math.sin(rand);
				Tweener.addTween( bs, { x:__x, y:__y, time:Math.random() * .05 + .15, delay:Math.random() * .2, transition:"easeInOutCubic", onUpdate:render } );
				
			});
			
		}
		
		public function expand():void {
			var __x:Number;
			var __y:Number;
			
			_callEverySegments( function( bs:BitmapSegment, i:int, j:int ):void {
				__x = -(bs._x2 = Math.random() * 20 - 10 + bs._x );
				__y = bs._y2 = Math.random() * 20 - 10 + bs._y;
				
				Tweener.addTween( bs, { x:__x, y:__y, time:Math.random() * .05 + .15, delay:Math.random() * .2, transition:"easeOutCubic", onUpdate:render } );
			});
		}
		
		public function destroy():void {
			
			Tweener.removeTweens(this, "flipT");
			
			_callEverySegments( function( bs:BitmapSegment, i:int, j:int ):void {
				Tweener.removeTweens( bs, "x", "y");
			});
			while ( numChildren ) {
				removeChildAt(0);
			}
			
			if ( parent ) {
				parent.removeChild( this );
			}
			
		}
		
		private function log( msg:*, priority:int = 0 ):void {
			Debugger.log( "[FlipPaper] " + String(msg), priority );
		}
		
	}

}